package com.wolfcode.flow.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;

import com.wolfcode.flow.domain.vo.BusBpmnInfoVo;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.wolfcode.flow.mapper.BusBpmnInfoMapper;
import com.wolfcode.flow.domain.BusBpmnInfo;
import com.wolfcode.flow.service.IBusBpmnInfoService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

/**
 * 流程定义明细Service业务层处理
 *
 * @author wolfcode
 * @date 2022-11-28
 */
@Service
public class BusBpmnInfoServiceImpl implements IBusBpmnInfoService {
    @Autowired
    private BusBpmnInfoMapper busBpmnInfoMapper;
    @Autowired
    private RepositoryService repositoryService;

    /**
     * 查询流程定义明细
     *
     * @param id 流程定义明细主键
     * @return 流程定义明细
     */
    @Override
    public BusBpmnInfo selectBusBpmnInfoById(Long id) {
        return busBpmnInfoMapper.selectBusBpmnInfoById(id);
    }

    /**
     * 查询流程定义明细列表
     *
     * @param busBpmnInfo 流程定义明细
     * @return 流程定义明细
     */
    @Override
    public List<BusBpmnInfo> selectBusBpmnInfoList(BusBpmnInfo busBpmnInfo) {
        return busBpmnInfoMapper.selectBusBpmnInfoList(busBpmnInfo);
    }

    /**
     * 新增流程定义明细
     *
     * @param busBpmnInfo 流程定义明细
     * @return 结果
     */
    @Override
    public int insertBusBpmnInfo(BusBpmnInfo busBpmnInfo) {
        return busBpmnInfoMapper.insertBusBpmnInfo(busBpmnInfo);
    }

    /**
     * 修改流程定义明细
     *
     * @param busBpmnInfo 流程定义明细
     * @return 结果
     */
    @Override
    public int updateBusBpmnInfo(BusBpmnInfo busBpmnInfo) {
        return busBpmnInfoMapper.updateBusBpmnInfo(busBpmnInfo);
    }

    /**
     * 批量删除流程定义明细
     *
     * @param ids 需要删除的流程定义明细主键
     * @return 结果
     */
    @Override
    public int deleteBusBpmnInfoByIds(Long[] ids) {
        return busBpmnInfoMapper.deleteBusBpmnInfoByIds(ids);
    }

    /**
     * 删除流程定义明细信息
     *
     * @param id 流程定义明细主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteBusBpmnInfoById(Long id) {
        Assert.notNull(id, "非法参数");
        BusBpmnInfo busBpmnInfo = busBpmnInfoMapper.selectBusBpmnInfoById(id);
        Assert.notNull(busBpmnInfo, "流程定义文件不存在");
        // TODO：这一期不考虑，流程实例是否启动，是否要挂起，慎用
        // 流程定义信息表的删除
        // 权限：超管才能删除
        // 级联删除
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(busBpmnInfo.getProcessDefinitionKey())
                .processDefinitionVersion(busBpmnInfo.getVersion().intValue())
                .singleResult();
        Assert.notNull(processDefinition, "流程定义文件不存在");
        repositoryService.deleteDeployment(processDefinition.getDeploymentId(), true);
        // 删除部署的流程
        return busBpmnInfoMapper.deleteBusBpmnInfoById(id);
    }

    /**
     * 部署流程定义
     *
     * @param busBpmnInfoVo
     */
    @Override
    @Transactional
    public void deploy(BusBpmnInfoVo busBpmnInfoVo) {
        Assert.notNull(busBpmnInfoVo, "非法参数");
        // 1. 文件上传，文件格式校验，bpmn文件
        Assert.notNull(busBpmnInfoVo.getFile(), "文件不能为空");
        String originalFilename = busBpmnInfoVo.getFile().getOriginalFilename();
        Assert.notNull(originalFilename, "文件名获取失败");
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        Assert.state("bpmn".equals(suffix), "文件上传格式不正确，需要bpmn文件");
        // 方式二
        //Assert.state(filename.endsWith(".bpmn"), "请上传bpmn文件");

        // 2. 部署流程定义
        // spring容器中已经加入，AutoWired直接从容器拿即可
//        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
//        System.out.println(defaultProcessEngine);
//        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();

        try {
            InputStream inputStream = busBpmnInfoVo.getFile().getInputStream();
            Deployment deploy = repositoryService.createDeployment()
                    .name(originalFilename)
                    .addInputStream(originalFilename, inputStream)
                    .deploy();

            BusBpmnInfo busBpmnInfo = new BusBpmnInfo();
            // 获取流程定义表信息 查询已部署好的信息
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
            // 3. 落库bpmnInfo表
            busBpmnInfo.setProcessDefinitionKey(processDefinition.getKey());
            busBpmnInfo.setVersion(Long.valueOf(processDefinition.getVersion()));

            busBpmnInfo.setBpmnLabel(busBpmnInfoVo.getBpmnLabel());
            busBpmnInfo.setBpmnType(busBpmnInfoVo.getBpmnType());
            busBpmnInfo.setDeployTime(deploy.getDeploymentTime());
            busBpmnInfo.setInfo(busBpmnInfoVo.getInfo());
            busBpmnInfoMapper.insertBusBpmnInfo(busBpmnInfo);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public InputStream getResource(String type, Long id) {
        Assert.notNull(type, "非法参数");
        // 图片类型
        // bpmn_info:id---process_definition_key,version
        BusBpmnInfo busBpmnInfo = busBpmnInfoMapper.selectBusBpmnInfoById(id);
        Assert.notNull(busBpmnInfo, "不存在部署流程文件");
        // re_procdef: process_definition_key,version---deployment_id
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(busBpmnInfo.getProcessDefinitionKey())
                .processDefinitionVersion(busBpmnInfo.getVersion().intValue())
                .singleResult();
        Assert.notNull(processDefinition, "不存在部署流程文件");
        String deploymentId = processDefinition.getDeploymentId();
        String resourceName = processDefinition.getResourceName();
        // ge_bytearray: byte数组--->deployment_id
        // 直接返回就是xml格式
        if ("xml".equals(type.trim()))
            return repositoryService.getResourceAsStream(deploymentId, resourceName);
        // 图片类型
        DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        // generateDiagram(bpmn模型，需要高亮节点ID集合，需要高亮连线ID集合)
        // 查看进度的时候
        // bpmnModel bpmnModel,流程定义对象
        // List<String> highLightedActivities,需要高亮节点ID集合
        // List<String> highLightedFlows,需要高亮连线ID集合
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
        InputStream is = generator.generateDiagram(bpmnModel,
                Collections.EMPTY_LIST,
                Collections.EMPTY_LIST,
                "宋体",
                "宋体",
                "宋体"
        );
        return is;
    }

    @Override
    public BusBpmnInfo getBpmnType(int BpmnType) {

        return busBpmnInfoMapper.getByBpmnType(BpmnType);
    }
}
